package com.zy.datareceiver.binsess.warning.service.impl;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.zy.datareceiver.binsess.decode.service.StorageTaskService;
import com.zy.datareceiver.binsess.status.mapper.SendInfoMapper;
import com.zy.datareceiver.binsess.warning.email.service.EmailService;
import com.zy.datareceiver.binsess.status.entity.SendInfo;
import com.zy.datareceiver.binsess.warning.entity.SmsMassage;
import com.zy.datareceiver.binsess.warning.entity.WarningData;
import com.zy.datareceiver.binsess.warning.entity.WarningReceiver;
import com.zy.datareceiver.binsess.warning.mapper.WarningDataMapper;
import com.zy.datareceiver.binsess.warning.mapper.WarningReceiverMapper;
import com.zy.datareceiver.core.cast.CacheDict;
import com.zy.datareceiver.core.cast.ConCast;
import com.zy.datareceiver.core.cast.WarnType;
import com.zy.datareceiver.core.common.SpringApplicationContext;
import com.zy.datareceiver.core.utils.DateUtil;
import com.zy.datareceiver.core.utils.JsonUtil;
import com.zy.datareceiver.core.utils.SmsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

public class WarningDataTask extends Thread{
    private  static final Logger log = LoggerFactory.getLogger(WarningDataTask.class);

    private WarningDataMapper warningDataMapper = SpringApplicationContext.getBean(WarningDataMapper.class);
    private WarningReceiverMapper warningReceiverMapper = SpringApplicationContext.getBean(WarningReceiverMapper.class);
    private SendInfoMapper sendInfoMapper = SpringApplicationContext.getBean(SendInfoMapper.class);

    private EmailService emailService = SpringApplicationContext.getBean(EmailService.class);
    private BlockingQueue<WarningData> smsQueue = new LinkedBlockingDeque<>(ConCast.QueueSize.SMS_QUEUE_SIZE);
    private List<WarningReceiver> receivers ;
    private Map<String,Long> sendMessageMap = new HashMap<>();
    private Map<String,WarningData> decodeWarningDataMap = new HashMap<>();


    @Override
    public void run() {
        long now = System.currentTimeMillis();
        List<WarningData> warningDataList = new ArrayList<>();
        new Thread(){
            @Override
            public void run() {
                receivers = warningReceiverMapper.selectAll();
                try {
                    while (true){
                        WarningData warningData = smsQueue.take();
                        if (!isSended(warningData)){
//                            sendSms(warningData, WarnType.WARNING_DATA);
//                            sendEmail(warningData,WarnType.WARNING_DATA);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        try {
            while(true){

                WarningData warningData = StorageTaskService.warningQueue.take();
                warningDataList.add(warningData);
                smsQueue.put(warningData);
                if (warningDataList.size() > 1 && System.currentTimeMillis() - now > 1000){
                    warningDataMapper.batchInsert(warningDataList);

                    warningDataList.clear();
                    now = System.currentTimeMillis();
                }

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public boolean isSended(WarningData warningData){
        String pointName = CacheDict.getPointNameByPointId(warningData.getPointId());
        String parameterName = CacheDict.getParameterNameByParameterId(warningData.getParameterId());
        if (pointName == null || parameterName == null){
            return true;
        }
        String phoneMsg = pointName + "-" +parameterName;
        String warnLevel = CacheDict.getWarningLevelNameByLevelId(warningData.getLevelId());//CacheDict.getInstance().getDataDictionary().get(ConCast.Dict.WARNING_LEVEL_KEY).get(warningData.getLevelId());
        String sendMsg = phoneMsg + warnLevel;
        if (sendMessageMap.containsKey(sendMsg)){
            Long time = sendMessageMap.get(sendMsg);
            if (System.currentTimeMillis() - time > ConCast.Sms.DECODE_MESSAGE_TIME){
                if (decodeWarningDataMap.containsKey(sendMsg)){
                    WarningData warningData1 = decodeWarningDataMap.get(sendMsg);
                    if (warningData1 != null){
                        sendSms(warningData1, WarnType.RELIEVE_DATA);
                        sendEmail(warningData1,WarnType.RELIEVE_DATA);
                    }
                }
            }
            //一天之内，只发送一次短信
            if (System.currentTimeMillis() - time < ConCast.Sms.SHORT_MESSAGE_SENDING_CYCLE){
                return true;
            }
        }
        return false;
    }
    private void sendSms(WarningData warningData,WarnType warnType) {
        String pointName = CacheDict.getPointNameByPointId(warningData.getPointId());
        String parameterName = CacheDict.getParameterNameByParameterId(warningData.getParameterId());
        if (pointName == null || parameterName == null){
            return ;
        }
        String phoneMsg = pointName + "-" +parameterName;
        String warnLevel = CacheDict.getWarningLevelNameByLevelId(warningData.getLevelId());//CacheDict.getInstance().getDataDictionary().get(ConCast.Dict.WARNING_LEVEL_KEY).get(warningData.getLevelId());
        String sendMsg = phoneMsg + warnLevel;
        switch (warnType) {
            case WARNING_DATA: //发送预警数据
                SmsMassage warnMsg = new SmsMassage();
                warnMsg.setDevice(phoneMsg);
                warnMsg.setGrade(warnLevel);
                warnMsg.setProjectName("9#门机");
                warnMsg.setTriggertime(String.valueOf(warningData.getWarningTime()));

                for (WarningReceiver receiver : receivers) {
                    warnMsg.setUsername(receiver.getReceiverName());
                    String smsMessage = JsonUtil.obj2String(warnMsg);

                    SendInfo sendInfo = new SendInfo();
                    sendInfo.setReceiver(receiver.getReceiverName());
                    sendInfo.setMessage(smsMessage);
                    sendInfo.setSender("中岩物联");
                    sendInfo.setSendTime(DateUtil.format(new Date(), DateUtil.PATTERN_YYYY_MM_DD_HHMMSS));
                    sendInfo.setType(0);
                    SendSmsResponse response = null;
                    try {
                        response = SmsUtil.sendSms(receiver.getReceiverPhone(), JsonUtil.obj2String(warnMsg));
                    } catch (Exception e) {
                        log.error("短信发送异常");
                    }
                    if ("OK".equals(response.getCode())) {
                        sendInfo.setStatus(1);
                    } else {
                        sendInfo.setStatus(2);
                    }
                    sendInfoMapper.insert(sendInfo);
                }
                sendMessageMap.put(sendMsg, System.currentTimeMillis());
                break;
            case RELIEVE_DATA: //预警取消数据
                SmsMassage nomoreMsg = new SmsMassage();
                nomoreMsg.setDevice(phoneMsg);
                nomoreMsg.setGrade(warnLevel);
                nomoreMsg.setProjectName("9#门机");
                nomoreMsg.setTriggertime(String.valueOf(warningData.getWarningTime()));

                for (WarningReceiver receiver : receivers) {
                    nomoreMsg.setUsername(receiver.getReceiverName());
                    String smsMessage = JsonUtil.obj2String(nomoreMsg);

                    SendInfo sendInfo = new SendInfo();
                    sendInfo.setReceiver(receiver.getReceiverName());
                    sendInfo.setMessage(smsMessage);
                    sendInfo.setSender("中岩物联");
                    sendInfo.setSendTime(DateUtil.format(new Date(), DateUtil.PATTERN_YYYY_MM_DD_HHMMSS));
                    sendInfo.setType(0);
                    SendSmsResponse response = null;
                    try {
                        response = SmsUtil.sendSms(receiver.getReceiverPhone(), JsonUtil.obj2String(nomoreMsg));
                    } catch (Exception e) {
                        log.error("短信发送异常");
                    }
                    if ("OK".equals(response.getCode())) {
                        sendInfo.setStatus(1);
                    } else {
                        sendInfo.setStatus(2);
                    }
                    sendInfoMapper.insert(sendInfo);
                }
                sendMessageMap.put(sendMsg, System.currentTimeMillis());
                break;
            default:
                break;
        }
    }

    public String getWarningMessage(WarningData warningData){
        //todo 预警解除短信模板更改
        String pointName = CacheDict.getPointNameByPointId(warningData.getPointId());
        String parameterName = CacheDict.getParameterNameByParameterId(warningData.getParameterId());
        if (pointName == null || parameterName == null){
            return "";
        }
        String phoneMsg = pointName + "-" +parameterName;
        String warnLevel = CacheDict.getWarningLevelNameByLevelId(warningData.getLevelId());//CacheDict.getInstance().getDataDictionary().get(ConCast.Dict.WARNING_LEVEL_KEY).get(warningData.getLevelId());
        String sendMsg = phoneMsg + warnLevel;

        StringBuilder res = new StringBuilder();
        res.append("在").append(warningData.getWarningTime()).append("9#门机项目，监测点").append(phoneMsg).append("发生了").append(warnLevel).append(" ,中岩物联将持续为您关注");
        return res.toString();
    }

    private void sendEmail(WarningData warningData,WarnType warnType){
        String pointName = CacheDict.getPointNameByPointId(warningData.getPointId());
        String parameterName = CacheDict.getParameterNameByParameterId(warningData.getParameterId());
        if (pointName == null || parameterName == null){
            return ;
        }
        String phoneMsg = pointName + "-" +parameterName;
        String warnLevel = CacheDict.getWarningLevelNameByLevelId(warningData.getLevelId());//CacheDict.getInstance().getDataDictionary().get(ConCast.Dict.WARNING_LEVEL_KEY).get(warningData.getLevelId());
        String sendMsg = phoneMsg + warnLevel;

        switch (warnType) {
            case WARNING_DATA: //发送预警数据
                for (WarningReceiver receiver:receivers) {
                    SendInfo mailInfo = new SendInfo();
                    String message = "尊敬的:"+receiver.getReceiverName()+"在" +
                            DateUtil.format(new Date(),DateUtil.PATTERN_YYYY_MM_DD_HHMMSS)+", 9#门机项目"+phoneMsg+"发生了"+warnLevel+"级预警,中岩物联将持续为您关注";
                    emailService.sendSimpleMail(receiver.getReceiverEmail(),"中岩物联安全预警通知",message);
                    mailInfo.setMessage(message);
                    mailInfo.setReceiver(receiver.getReceiverName());
                    mailInfo.setSender("中岩物联");
                    mailInfo.setStatus(1);
                    mailInfo.setSendTime(DateUtil.format(new Date(),DateUtil.PATTERN_YYYY_MM_DD_HHMMSS));
                    mailInfo.setType(1);
                    sendInfoMapper.insert(mailInfo);
                }
                sendMessageMap.put(sendMsg, System.currentTimeMillis());
                break;
            case RELIEVE_DATA: //预警取消数据
                for (WarningReceiver receiver:receivers) {
                    SendInfo mailInfo = new SendInfo();
                    String message = "尊敬的:"+receiver.getReceiverName()+"在" +
                            DateUtil.format(new Date(),DateUtil.PATTERN_YYYY_MM_DD_HHMMSS)+", 9#门机项目"+phoneMsg+"发生的"+warnLevel+"级预警已经解除,中岩物联将持续为您关注";
                    emailService.sendSimpleMail(receiver.getReceiverEmail(),"中岩物联安全预警通知",message);
                    mailInfo.setMessage(message);
                    mailInfo.setReceiver(receiver.getReceiverName());
                    mailInfo.setSender("中岩物联");
                    mailInfo.setStatus(1);
                    mailInfo.setSendTime(DateUtil.format(new Date(),DateUtil.PATTERN_YYYY_MM_DD_HHMMSS));
                    mailInfo.setType(1);
                    sendInfoMapper.insert(mailInfo);
                }
                break;
            default:
        }
    }
}
